/*

	Copyright (C) 2004-2005 Michael Liebscher <johnnycanuck@users.sourceforge.net>
	Copyright (C) 1997-2001 Id Software, Inc.

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

	See the GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

/*

 does clearing color and depth at the same time offer any beneft?
 should we use the depth sense reversing trick to avoid depth clears?
 
 */

#include "../wolfiphone.h"
#import "../koth.h"
#import "../koth/KothConstants.h"
#import "JWSound.h"
#import "JWConfigureControls.h"


cvar_t	*controlScheme;
cvar_t	*sensitivity;
cvar_t	*stickTurnBase;
cvar_t	*stickTurnScale;
cvar_t	*stickMoveBase;
cvar_t	*stickMoveScale;
cvar_t	*stickDeadBand;
cvar_t	*tiltTurn;
cvar_t	*tiltMove;
cvar_t	*tiltDeadBand;
cvar_t	*tiltAverages;
cvar_t	*tiltFire;
cvar_t	*music;
cvar_t	*showTilt;
cvar_t	*showTime;
cvar_t	*cropSprites;
cvar_t	*blends;
cvar_t	*gunFrame;
cvar_t	*slowAI;
cvar_t	*revLand;
cvar_t	*mapScale;
cvar_t	*hideControls;
cvar_t	*autoFire;

W32	sys_frame_time;

//JWLandscape* landscape = nil;
JWPicker* picker = nil;

void koth_init();
void init_managers();
void koth_shutdown();


void Sys_Error( const char *format, ... )
{ 
    va_list     argptr;
    char        string[ 1024 ];

    va_start( argptr, format );
    (void)vsnprintf( string, sizeof( string ), format, argptr );
    va_end( argptr );

	fprintf( stderr, "Error: %s\n", string );

	_exit( 1 );

} 

void Sys_Quit (void)
{
	_exit( 0 );
}

void Sys_SendKeyEvents (void)
{
}

char *Sys_GetClipboardData( void )
{
	return NULL;
}

void Reset_f() {
	memset( &currentMap, 0, sizeof( currentMap ) );
	currentMap.skill = 1;
	cvar_vars = NULL;	// don't write any cvars to the config file
	iphoneShutdown();
}

/*
 ==================
 iphoneStartup
 
 ==================
 */
void iphoneStartup() {
	char	*s;
	int		start = Sys_Milliseconds();

	// temporary 
	const char *systemVersion = SysIPhoneGetOSVersion();
	printf( "systemVersion = %s\n", systemVersion );
	
	z_chain.next = z_chain.prev = &z_chain;
	
	InitImmediateModeGL();
	
	// Prepare enough of the subsystems to handle
	// cvar and command buffer management.
	COM_InitArgv( 0, NULL );		// FIXME: get args...
	
	Cmd_Init();
	Cvar_Init();
	Con_Init();
	FS_InitFilesystem();	
	
	// We need to add the early commands twice, because
	// a basedir or cddir needs to be set before execing
	// config files, but we want other parms to override
	// the settings of the config files.
	Cbuf_AddEarlyCommands( false );
	Cbuf_Execute();
	
	R_Init();

	Cmd_AddCommand( "reset", Reset_f );

	developer = Cvar_Get( "developer", "0", CVAR_INIT );
	logfile_active = Cvar_Get( "logfile", "0", CVAR_INIT );
	
	s = va( "%s %s %s %s %s %s", APP_VERSION, RELEASENAME, CPUSTRING, __DATE__, __TIME__, BUILDSTRING );
	Cvar_Get( "version", s, CVAR_SERVERINFO | CVAR_NOSET );
	
	Con_Init();
	
	//Sound_Init();
	
	Game_Init();	// game and player init
	
	Cbuf_AddText( "exec config.cfg\n" );
	Cbuf_AddEarlyCommands( true );
	Cbuf_Execute();
	
	// add + commands from command line
	Cbuf_AddLateCommands();
	Cbuf_Execute();
	
	Com_Printf( "\n====== Application Initialized ======\n\n" );	
	
	//Sound_Activate( true );
	consoleActive = 0;
	
	controlScheme = Cvar_Get( "controlScheme", "0", CVAR_ARCHIVE );
	sensitivity = Cvar_Get( "sensitivity", "0.3", CVAR_ARCHIVE );
	stickTurnBase = Cvar_Get( "stickTurnBase", "300", CVAR_ARCHIVE );
	stickTurnScale = Cvar_Get( "stickTurnScale", "500", CVAR_ARCHIVE );
	stickMoveBase = Cvar_Get( "stickMoveBase", "3000", CVAR_ARCHIVE );
	stickMoveScale = Cvar_Get( "stickMoveScale", "5000", CVAR_ARCHIVE );
	stickDeadBand = Cvar_Get( "stickDeadBand", "0.2", CVAR_ARCHIVE );
	tiltTurn = Cvar_Get( "tiltTurn", "0", CVAR_ARCHIVE );
	tiltMove = Cvar_Get( "tiltMove", "0", CVAR_ARCHIVE );
	tiltFire = Cvar_Get( "tiltFire", "0", CVAR_ARCHIVE );
	music = Cvar_Get( "music", "1", CVAR_ARCHIVE );
	tiltDeadBand = Cvar_Get( "tiltDeadBand", "0.08", CVAR_ARCHIVE );
	tiltAverages = Cvar_Get( "tiltAverages", "3", CVAR_ARCHIVE );
	cropSprites = Cvar_Get( "cropSprites", "1", 0 );
	showTilt = Cvar_Get( "showTilt", "-1", 0 );
	showTime = Cvar_Get( "showTime", "0", 0 );
	blends = Cvar_Get( "blends", "1", 0 );
	gunFrame = Cvar_Get( "gunFrame", "0", 0 );
	slowAI = Cvar_Get( "slowAI", "0", 0 );
	revLand = Cvar_Get( "revLand", "0", CVAR_ARCHIVE );
	mapScale = Cvar_Get( "mapScale", "10", CVAR_ARCHIVE );
	hideControls = Cvar_Get( "hideControls", "0", CVAR_ARCHIVE );
	autoFire = Cvar_Get( "autoFire", "0", 0 );
	
	// make sure volume changes and incoming calls draw the right orientation
	SysIPhoneSetUIKitOrientation( revLand->value );
	
	/*
	// preload all the ogg FM synth sounds
	Com_Printf( "before ogg preload: %i msec\n", Sys_Milliseconds() - start );
	
	Sound_RegisterSound( "lsfx/001.wav" );
	Sound_RegisterSound( "lsfx/003.wav" );
	Sound_RegisterSound( "lsfx/008.wav" );
	Sound_RegisterSound( "lsfx/009.wav" );
	Sound_RegisterSound( "lsfx/012.wav" );
	Sound_RegisterSound( "lsfx/023.wav" );
	Sound_RegisterSound( "lsfx/028.wav" );
	Sound_RegisterSound( "lsfx/030.wav" );
	Sound_RegisterSound( "lsfx/031.wav" );
	Sound_RegisterSound( "lsfx/033.wav" );
	Sound_RegisterSound( "lsfx/034.wav" );
	Sound_RegisterSound( "lsfx/035.wav" );
	Sound_RegisterSound( "lsfx/036.wav" );
	Sound_RegisterSound( "lsfx/037.wav" );
	Sound_RegisterSound( "lsfx/038.wav" );
	Sound_RegisterSound( "lsfx/040.wav" );
	Sound_RegisterSound( "lsfx/045.wav" );
	Sound_RegisterSound( "lsfx/061.wav" );
	Sound_RegisterSound( "lsfx/062.wav" );
	Sound_RegisterSound( "lsfx/064.wav" );
	Sound_RegisterSound( "lsfx/069.wav" );
	Sound_RegisterSound( "lsfx/076.wav" );
	Sound_RegisterSound( "lsfx/078.wav" );
	Sound_RegisterSound( "lsfx/080.wav" );
	Sound_RegisterSound( "lsfx/085.wav" );
	Sound_RegisterSound( "lsfx/086.wav" );
	*/
	
	// these should get overwritten by LoadTheGame
	//memset( &currentMap, 0, sizeof( currentMap ) );
	//currentMap.skill = 1;
	//currentMap.episode = 0;
	//HudSetForScheme( 0 );
	
	Com_Printf( "before LoadTheGame: %i msec\n", Sys_Milliseconds() - start );
	
	if ( !LoadTheGame() ) {
		//PL_NewGame( &Player );
		//iphoneStartMap( currentMap.episode, currentMap.map, currentMap.skill );
	}	
	
	// KotH Stuff.
	koth_init();

	// always start at main menu
	menuState = IPM_MAIN;
	
	Com_Printf( "startup time: %i msec\n", Sys_Milliseconds() - start );
}

/*
 ===================
 iphonePreloadBeforePlay
 
 This couold all be done at startup, but moving a bit of the delay
 to after pressing the resume button works a little better.
 ===================
*/
#if 0
void iphonePreloadBeforePlay() {
	int	start = Sys_Milliseconds();
	
	// the texnums might have been different in the savegame
	HudSetTexnums();
	
	// preload all the other game gui textures that might pop up
	TM_FindTexture( "iphone/gold_key.tga", TT_Pic );
	TM_FindTexture( "iphone/silver_key.tga", TT_Pic );
	TM_FindTexture( "iphone/L_damage.tga", TT_Pic );
	TM_FindTexture( "iphone/R_damage.tga", TT_Pic );
	
	for ( int i = 0 ; i < 10 ; i++ ) {
		char	name[64];
		sprintf( name, "iphone/%i.tga", i );
		numberPics[i] = TM_FindTexture( name, TT_Pic );
	}
	
	for ( int i = 0 ; i < NUM_MUGSHOTS ; i++ ) {
		TM_FindTexture( mugshotnames[ i ], TT_Pic );
	}
	
	Sound_RegisterSound( "sfx/001.wav" );
	Sound_RegisterSound( "sfx/002.wav" );
	Sound_RegisterSound( "sfx/007.wav" );
	Sound_RegisterSound( "sfx/010.wav" );
	Sound_RegisterSound( "sfx/011.wav" );
	Sound_RegisterSound( "sfx/012.wav" );
	Sound_RegisterSound( "sfx/013.wav" );
	Sound_RegisterSound( "sfx/015.wav" );
	Sound_RegisterSound( "sfx/022.wav" );
	Sound_RegisterSound( "sfx/024.wav" );
	Sound_RegisterSound( "sfx/025.wav" );
	Sound_RegisterSound( "sfx/026.wav" );
	Sound_RegisterSound( "sfx/027.wav" );
	Sound_RegisterSound( "sfx/035.wav" );
	Sound_RegisterSound( "sfx/037.wav" );
	Sound_RegisterSound( "sfx/046.wav" );
	Sound_RegisterSound( "sfx/049.wav" );
	Sound_RegisterSound( "sfx/071.wav" );
	Sound_RegisterSound( "sfx/074.wav" );
	Sound_RegisterSound( "sfx/076.wav" );
	Sound_RegisterSound( "sfx/086.wav" );
	Sound_RegisterSound( "sfx/088.wav" );
	Sound_RegisterSound( "sfx/105.wav" );
	Sound_RegisterSound( "sfx/107.wav" );
	
	Com_Printf( "preloadBeforePlay(): %i msec\n", Sys_Milliseconds() - start );	
}
#endif
/*
 ==================
 iphoneWriteConfig
 
 ==================
 */
void iphoneWriteConfig( void ) {
	FILE	*fp;
	char	path[ MAX_OSPATH];
	cvar_t	*var;
	char	buffer[1024];
	
	my_snprintf( path, sizeof( path ), "%s/config.cfg", iphoneDocDirectory );
	fp = fopen( path, "w" );
	if( ! fp ) {
		Com_Printf( "Could not write config.cfg.\n" );
		return;
	}
	
	// write out commands to set the archived cvars
	for( var = cvar_vars ; var ; var = var->next ) {
		if( var->flags & CVAR_ARCHIVE ) {
			my_snprintf( buffer, sizeof( buffer ), "set %s \"%s\"\n", var->name, var->string );
			fprintf( fp, "%s", buffer );
			Com_Printf( "%s", buffer );
		}
	}
	
	fclose( fp );
	koth_shutdown();
}


/*
 ==================
 iphoneShutdown
 
 Save the game at this position
 ==================
 */
void iphoneShutdown() {
	//Sound_StopAllSounds();
	//Sound_StopBGTrack();
	iphoneWriteConfig();
	SaveTheGame();
	exit( 0 );
}


void koth_init()
{	
	init_managers();
	
	NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
	NSNumber* storedMaxLevel = [defaults objectForKey:@"maxLevel"];
	if(!storedMaxLevel) {
		maxLevel = 1;
	} else {
		maxLevel = [storedMaxLevel unsignedIntValue];
	}		
	
	// !!!! Remove !!!!
	//if(maxLevel < 1000) {
	//	maxLevel = 1000;
	//}
	
	[JWConfigureControls loadControlConfiguration];
	
	NSString* docsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
	NSString* archivePath = [docsPath stringByAppendingPathComponent:@"landscape.archive"];
	JWLandscape* landscape = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath];
	
	if(!landscape) {
		landscape = [[[JWLandscape alloc] initWithLevel:1 populate:YES] autorelease];
	} else {
		JWSquare* playerSquare = [landscape getSquareAtX:Player.position.origin[0] z:-Player.position.origin[1]];
		playerSquare.player = YES;
	}
	
	assert(landscape);
	setLevelColours(landscape.level);
	JWLandscapeManager* landscapeManager = [[[JWLandscapeManager alloc] initWithEntity:landscape] autorelease];
	[[JWManagers sharedManager] addManager:landscapeManager];
	picker = [[JWPicker alloc] initWithLandscape:landscape];
}

void init_managers()
{
	[JWSound soundManager];
	JWBoxManager* boxManager = [[[JWBoxManager alloc] initWithEntity:nil] autorelease];
	JWRobotManager* robotManager = [[[JWRobotManager alloc] initWithEntity:nil] autorelease];
	JWSentinelManager* sentinelManager = [[[JWSentinelManager alloc] initWithEntity:nil] autorelease];
	JWTreeManager* treeManager = [[[JWTreeManager alloc] initWithEntity:nil] autorelease];
	
	[[JWManagers sharedManager] removeAllManagers];
	[[JWManagers sharedManager] addManager:boxManager];
	[[JWManagers sharedManager] addManager:robotManager];
	[[JWManagers sharedManager] addManager:treeManager];
	[[JWManagers sharedManager] addManager:sentinelManager];
}

void koth_shutdown()
{
	NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
	[defaults setObject:[NSNumber numberWithUnsignedInt:maxLevel] forKey:@"maxLevel"];
	[defaults synchronize];
	
	[JWConfigureControls saveControlConfiguration];
	
	NSString* docsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
	NSString* archivePath = [docsPath stringByAppendingPathComponent:@"landscape.archive"];
	
	NSObject<JWManager>* landscapeManager = [[JWManagers sharedManager] managerOfClass:[JWLandscapeManager class]];
	NSObject<JWEntity>* landscape = [landscapeManager entity];
	BOOL result = [NSKeyedArchiver archiveRootObject:landscape toFile:archivePath];
	assert(result);
	
	[picker release];
	
	[[JWManagers sharedManager] removeAllManagers];
	[[JWManagers sharedManager] release];
}
